import socket
import sys
import struct
import time
import pymysql
import datetime


# 实现采集温度传感器和静力水准仪

def crc16(string):
    # data = bytes.fromhex(string)
    data = string
    crc = 0xFFFF
    for pos in data:
        crc ^= pos
        for i in range(8):
            if ((crc & 1) != 0):
                crc >>= 1
                crc ^= 0xA001
            else:
                crc >>= 1
    return hex(((crc & 0xff) << 8) + (crc >> 8))


# 连接数据库
def MySQLConnect():
    connection = pymysql.connect(
        host='localhost',  # IP，MySQL数据库服务器IP地址
        port=3306,  # 端口，默认3306，可以不输入
        user='root',  # 数据库用户名
        password='zhoushuai123',  # 数据库登录密码
        database='mysql',  # 要连接的数据库
        charset='utf8'  # 字符集，注意不是'utf-8'
    )
    return connection


# 插入温湿度采集到数据库
def AddData1(wd, sd, time):
    # 连接数据库
    conn = MySQLConnect()
    # 使用cursor()方法创建一个游标对象cursor
    cursor = conn.cursor()
    print("温度：", wd, "湿度：", sd, "时间：", time)
    # 插入数据库
    sql = "INSERT INTO wendu(temp, hum, time) VALUES (%s,%s,%s); "
    cursor.execute(sql, [wd, sd, time])
    # 提交事务
    conn.commit()
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    conn.close()


# 插入静力水准仪采集到数据库
def AddData2(id, water_level, time):
    # 连接数据库
    conn = MySQLConnect()
    # 使用cursor()方法创建一个游标对象cursor
    cursor = conn.cursor()
    # 插入数据库
    sql = "INSERT INTO jingli(id, water_level, time) VALUES (%s,%s,%s); "
    cursor.execute(sql, [id, water_level, time])
    # 提交事务
    conn.commit()
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    conn.close()


# 采集温度传感器的数据
def getDataTemp(cmd):
    # flag标志采集的次数
    flag = 0
    last = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    print(last)
    last1 = time.time()
    cmd = bytes.fromhex(cmd)
    # print(cmd)
    crc = crc16(cmd)
    crc = bytes.fromhex(crc[2:])
    # 得到发送的指令（modbus协议定义内容+校验）
    cmd = cmd + crc
    udp.sendto(cmd, ('demo-monitor.igong.com', 8001))
    try:
        data, addr = udp.recvfrom(8192)
    except socket.timeout:
        print("超时")
        sys.exit(1)
    crc = data[-2:]
    crc1 = crc16(data[:-2])
    crc1 = crc1[2:]
    if (len(crc1) == 3):
        crc1 = '0' + crc1
    crc1 = bytes.fromhex(crc1)

    # print(crc1)
    if crc != crc1:
        print("CRC16校验失败！")
        sys.exit(2)
    # 解析数据
    wd, sd = struct.unpack('>ii', data[4:12])
    wd = wd / 100.
    print("温度：", wd, "湿度：", sd)
    AddData1(wd, sd, last)
    flag = flag + 1
    while True:
        now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        # print(s)
        now1 = time.time()
        # 每隔5s获取一次数据
        if (now1 - last1 > 5):
            udp.sendto(cmd, ('demo-monitor.igong.com', 8001))
            try:
                data, addr = udp.recvfrom(8192)
            except socket.timeout:
                print("超时")
                sys.exit(1)
            crc = data[-2:]
            crc2 = bytes.hex(crc)
            # print(crc2)
            crc1 = crc16(data[:-2])
            crc1 = crc1[2:]
            if (len(crc1) == 3):
                crc1 = '0' + crc1
            # print(crc1)
            crc1 = bytes.fromhex(crc1)
            # print(crc1)
            if crc != crc1:
                print("CRC16校验失败！")
                sys.exit(2)
            # 解析数据
            wd, sd = struct.unpack('>ii', data[4:12])
            wd = wd / 100.0
            # 当前时间
            print(now)
            # 获取得到的数据
            print("温度：", wd, "湿度：", sd)
            last = now
            last1 = now1
            wd = str(wd)
            sd = str(sd)
            AddData1(wd, sd, now)
            flag = flag + 1
            if flag >= 5:
                str1 = input("请选择是否继续采集（y表示继续，n表示退出）：")
                if str1 == 'y':
                    flag = 0
                    continue
                else:
                    break


def getDataStaticLevel(cmd):
    id = cmd[0:2]
    # print(id)
    if id == '02':
        # print("2号")
        id = '00' + id
        getData(id, cmd)
    elif id == '03':
        # print("3号")
        id = '00' + id
        getData(id, cmd)
    elif id == '04':
        # print("4号")
        id = '00' + id
        getData(id, cmd)
    elif id == '05':
        # print("5号")
        id = '00' + id
        getData(id, cmd)


def getData(id, cmd):
    flag = 0
    last = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    print(last)
    last1 = time.time()
    cmd = bytes.fromhex(cmd)
    crc = crc16(cmd)
    crc = crc[2:]
    if (len(crc) == 3):
        crc = '0' + crc
    crc = bytes.fromhex(crc)
    cmd = cmd + crc
    udp.sendto(cmd, ('demo-monitor.igong.com', 8001))
    print("发送数据成功")
    try:
        data, address = udp.recvfrom(8192)
        # print(data)
    except socket.timeout:
        print("超时")
        sys.exit(1)
    # print(len(data))
    crc = data[-2:]
    # print(data[:-2])
    crc1 = crc16(data[:-2])
    # print(crc1)
    crc1 = crc1[2:]
    if len(crc1) == 3:
        crc1 = '0' + crc1
    # print(crc1)
    crc1 = bytes.fromhex(crc1)
    if crc != crc1:
        print("CRC16校验失败！")
        sys.exit(2)
    # print(data[4:8])
    nd = struct.unpack('>i', data[4:8])
    # print(nd)
    nd1 = nd[0] * 10.0
    nd1 = str(nd1)
    # print(last)
    print("挠度：" + nd1)
    AddData2(id, nd1, last)
    flag = flag + 1

    while True:

        now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        # print(s)
        now1 = time.time()
        # 每隔5s获取一次数据
        if (now1 - last1 > 5):
            udp.sendto(cmd, ('demo-monitor.igong.com', 8001))
            try:
                data, addr = udp.recvfrom(8192)
            except socket.timeout:
                print("超时")
                sys.exit(1)
            crc = data[-2:]
            crc2 = bytes.hex(crc)
            # print(crc2)
            crc1 = crc16(data[:-2])
            crc1 = crc1[2:]
            if (len(crc1) == 3):
                crc1 = '0' + crc1
            # print(crc1)
            crc1 = bytes.fromhex(crc1)
            # print(crc1)
            if crc != crc1:
                print("CRC16校验失败！")
                sys.exit(2)
            # 解析数据
            nd = struct.unpack('>i', data[4:8])
            nd = nd[0] * 10.0
            nd1 = str(nd)
            print(now)
            print("挠度：" + nd1)
            nd = str(nd)
            AddData2(id, nd1, now)
            last = now
            last1 = now1
            flag = flag + 1
            if flag >= 5:
                str1 = input("请选择是否继续采集（y表示继续，n表示退出）：")
                if str1 == 'y':
                    flag = 0
                    continue
                else:
                    break


if __name__ == '__main__':
    print("开始程序")
    print("程序相关说明：")
    print("本程序采用UDP协议，其中当输入指令为0就退出整个程序。")
    print("命令格式类似于地址（01，02，03，04，05）+03+传感器地址（0001）+传感器个数（0001，0002）")
    print("例如：010300010002（温度传感器），020300010001（静力水准仪1）")
    print("如果出现不合法指令就输出提示信息，并重新输入指令。")
    udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
    udp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    udp.settimeout(5)

    while True:
        cmd = input("请输入相关命令：")
        # print(len(cmd))
        num = cmd[8:]
        # print(num)
        if num == '0001' and cmd[0:2] == '01':
            print("此处不实现只对温度采集！！！")
        elif num == '0001':
            print("一个传感器")
            getDataStaticLevel(cmd)
        elif num == '0002':
            print("两个传感器")
            getDataTemp(cmd)
        elif cmd == '0':
            break
        else:
            print("指令不合法！！！")

